/***************************************************************************
 *   Copyright 2005-2009 Last.fm Ltd.                                      *
 *   Portions contributed by Casey Link, Lukasz Wisniewski,                *
 *   Mike Jennings, and Michael Novak Jr.                                  *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
 ***************************************************************************/
package fm.last.android;

import java.io.IOException;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;

/**
 * An implementation of LastFmServer
 * 
 * @author Mike Jennings
 * @author Casey Link
 */
final class LastFmServerImpl implements LastFmServer {
	private String api_key;
	private String shared_secret;
	private String baseUrl;

	LastFmServerImpl(String baseUrl, String api_key, String shared_secret) {
		this.baseUrl = baseUrl;
		this.api_key = api_key;
		this.shared_secret = shared_secret;
	}

	private Map<String, String> createParams(String method) {
		Map<String, String> params = new HashMap<String, String>();
		params.put("method", method);
		params.put("api_key", api_key);
		return params;
	}

	/**
	 * "sign" parameters in the way that last.fm expects.
	 * 
	 * See: http://www.last.fm/api/authspec#8
	 * 
	 * @param params
	 */
	private void signParams(Map<String, String> params) {
		StringBuilder sb = new StringBuilder();
		SortedSet<String> keySet = new TreeSet<String>(params.keySet());
		for (String key : keySet) {
			sb.append(key).append(params.get(key));
		}
		sb.append(shared_secret);
		String signature = sb.toString();
		String api_sig = MD5.getInstance().hash(signature);
		// now we pad to 32 chars if we need to:
		while (32 - api_sig.length() > 0)
			api_sig = "0" + api_sig;

		params.put("api_sig", api_sig);
	}

	public Session getMobileSession(String username, String authToken) throws IOException, WSError {
		Map<String, String> params = new HashMap<String, String>();
		if (username != null) {
			params.put("username", username);
		}
		if (authToken != null) {
			params.put("authToken", authToken);
		}
		params.put("method", "auth.getMobileSession");
		params.put("api_key", api_key);
		signParams(params); // apparently unrequired
		return AuthFunctions.getMobileSession(baseUrl, params);
	}
	
	public SessionInfo getSessionInfo(String sk) throws IOException, WSError {
		Map<String, String> params = createParams("auth.getSessionInfo");
		if (sk != null) {
			params.put("sk", sk);
			signParams(params);
		}
		return AuthFunctions.getSessionInfo(baseUrl, params);
	}

	public void signUp(String username, String password, String email) throws IOException {
		Map<String, String> params = createParams("user.signUp");
		params.put("username", username);
		params.put("password", password);
		params.put("email", email);
		signParams(params);
		UserFunctions.signUp(baseUrl, params);
	}

}